using System;
using System.Collections.Generic;
using System.Linq;
using Daemon.Model;
using Microsoft.AspNetCore.Mvc;
using Daemon.Repository.Contract;
using System.Net.Http;
using Microsoft.AspNetCore.Http;
using Daemon.Common;
using Daemon.Model;
using System.IO;
using System.Text;
using NPOI.XSSF.UserModel;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using Newtonsoft.Json;
using Daemon.Common.Exceptions;
using Daemon.Model.ViewModel;
using Daemon.Data.Substructure.Framework;
using Daemon.Service.Contract;
using System.Net;
namespace DaemonAPI.Controllers.V1
{
    [ApiController]
    [Route("daemonApi/[controller]")]
    public class OperationController : BaseApiController
    {
        private readonly IStudentImportTemplateRepository _studentImportTemplateRepository;
        private readonly IStudentRepository _studentRepository;
        private readonly IStudentGradeRepository _studentGradeRepository;
        private readonly IStudentClassRepository _studentClassRepository;
        private readonly IScoreImportService _scoreImportService;
        private readonly OperationManager _operationManager;

        public OperationController(
            IStudentImportTemplateRepository studentImportTemplateRepository,
        IStudentRepository studentRepository,
        IScoreImportService scoreImportService,
        IStudentGradeRepository studentGradeRepository,
        IStudentClassRepository studentClassRepository,
        OperationManager operationManager)
        {
            _studentImportTemplateRepository = studentImportTemplateRepository;
            _studentRepository = studentRepository;
            _scoreImportService = scoreImportService;
            _operationManager = operationManager;
            _studentGradeRepository = studentGradeRepository;
            _studentClassRepository = studentClassRepository;
        }

        [Route("{id}")]
        [HttpGet]
        public ResultModel Get(string id)
        {
            var obj = JsonConvert.DeserializeObject<Operation<ImportDataResult>>(_operationManager.Get(id).ToString());
            return new ResultModel(HttpStatusCode.OK, "", new List<Operation<ImportDataResult>>() { obj });
        }

        [Route("ImportScore")]
        [HttpPost]
        [DisableRequestSizeLimit]
        public ResultModel<Operation<ImportDataResult>> ImportScore(IFormFileCollection files, int templateId, int gradeId, int classId, int stageId)
        {
            if (files.Count == 0)
            {
                throw new BusinessException((int)BusinessCode.InCorrect, "", null);
            }

            var file = files[0];
            var bytes = new byte[file.Length];
            using (var stream = file.OpenReadStream())
            {
                using (var reader = new StreamReader(stream, Encoding.UTF8))
                {
                    reader.BaseStream.Read(bytes, 0, bytes.Length);
                    reader.BaseStream.Seek(0, SeekOrigin.Begin);
                    IWorkbook workbook = WorkbookFactory.Create(stream, ImportOption.All);
                    HSSFWorkbook xlsBook;

                    // return if the file is an actual .xls file
                    if (!workbook.GetType().Equals(typeof(HSSFWorkbook)))
                    {
                        // convert .xlsx to .xls
                        xlsBook = NPOIHelper.ConverXSSFToHSSF((XSSFWorkbook)workbook);
                    }
                    else
                    {
                        xlsBook = (HSSFWorkbook)workbook;
                    }

                    var dataDic = NPOIHelper.GetExcelData(xlsBook);
                    var result = _scoreImportService.ImportScore(dataDic, templateId, gradeId, classId, stageId);
                    var operation = _operationManager.Register(result.Key, result);
                    return new ResultModel<Operation<ImportDataResult>>(HttpStatusCode.OK, operation);
                }
            }
        }

        [Route("ImportStudent")]
        [HttpPost]
        [DisableRequestSizeLimit]
        public ResultModel ImportStudent(IFormFileCollection files, int classId, int gradeId, int templateId)
        {
            if (files.Count == 0)
            {
                throw new BusinessException((int)BusinessCode.InCorrect, "请先选择文件！", null);
            }

            var file = files[0];
            var bytes = new byte[file.Length];
            var importStudents = new List<Student>();
            using (var stream = file.OpenReadStream())
            {
                using (var reader = new StreamReader(stream, Encoding.UTF8))
                {
                    reader.BaseStream.Read(bytes, 0, bytes.Length);
                    reader.BaseStream.Seek(0, SeekOrigin.Begin);
                    IWorkbook workbook = WorkbookFactory.Create(stream, ImportOption.All);
                    HSSFWorkbook xlsBook;

                    // return if the file is an actual .xls file
                    if (!workbook.GetType().Equals(typeof(HSSFWorkbook)))
                    {
                        // convert .xlsx to .xls
                        xlsBook = NPOIHelper.ConverXSSFToHSSF((XSSFWorkbook)workbook);
                    }
                    else
                    {
                        xlsBook = (HSSFWorkbook)workbook;
                    }

                    var dataDic = NPOIHelper.GetExcelData(xlsBook);
                    if (dataDic.Count > 0)
                    {
                        var studentImportTemplate = _studentImportTemplateRepository.FindById(templateId);
                        var templateInfos = JsonConvert.DeserializeObject<List<TemplateMapping>>(studentImportTemplate.TemplateJson);
                        var sheetNameInfo = templateInfos.Find(r => r.ColumnName == "SheetName");
                        if (sheetNameInfo == null)
                        {
                            throw new BusinessException((int)BusinessCode.InCorrect, "模板信息不正确！", null);
                        }

                        var sheetName = sheetNameInfo.SheetName;
                        if (dataDic.TryGetValue(sheetName, out List<List<string>> studentInfos))
                        {
                            var classInfo = _studentClassRepository.FindAll().First(r => r.Id == classId);
                            var gradeInfo = _studentGradeRepository.FindAll().First(r => r.Id == gradeId);
                            if (studentInfos == null)
                            {
                                throw new BusinessException((int)BusinessCode.InCorrect, "导入失败！", null);
                            }

                            var startRowInfo = templateInfos.Find(r => r.ColumnName == "StartRow");
                            if (startRowInfo == null || !startRowInfo.CellIndex.HasValue)
                            {
                                throw new BusinessException((int)BusinessCode.InCorrect, "模板信息不正确！", null);
                            }

                            for (int i = startRowInfo.CellIndex.Value; i < studentInfos.Count; i++)
                            {
                                var student = MapStudent(studentInfos[i], classInfo, gradeInfo, templateInfos, classId, gradeId);
                                if (student != null)
                                {
                                    importStudents.Add(student);
                                }
                            }
                        }
                        else
                        {
                            throw new BusinessException((int)BusinessCode.InCorrect, "导入失败！", null);
                        }
                    }
                }
            }

            if (importStudents.Any())
            {
                _studentRepository.AddRangeByDBContext(importStudents);
            }

            return new ResultModel(System.Net.HttpStatusCode.OK, "导入成功！", null);
        }

        private Student MapStudent(List<string> cellInfos, StudentClass classInfo, StudentGrade gradeInfo, List<TemplateMapping> templateInfos, int classId, int gradeId)
        {
            var schoolId = HttpContext.Request.HttpContext.User.Claims.FirstOrDefault(r => r.Type == "SchoolId");
            var student = new Student() { ClassId = classId, GradeId = gradeId };
            if (!string.IsNullOrEmpty(schoolId?.Value))
            {
                student.SchoolId = Convert.ToInt32(schoolId.Value);
            }

            templateInfos.ForEach(template =>
            {
                var property = student.GetType().GetProperty(template.ColumnName);

                object value = null;
                if (property != null && template.CellIndex.HasValue && template.ColumnName != "ClassId" && template.ColumnName != "GradeId")
                {
                    value = cellInfos[template.CellIndex.Value];

                    if (value != null)
                    {
                        property.SetValue(student, value);
                    }
                }
            });

            var classTemplate = templateInfos.Find(r => r.ColumnName == "ClassId");
            if (classTemplate != null && classTemplate.CellIndex.HasValue)
            {
                var className = cellInfos[classTemplate.CellIndex.Value];
                if (className != classInfo.Name)
                {
                    return null;
                }
            }

            var gradeTemplate = templateInfos.Find(r => r.ColumnName == "GradeId");
            if (gradeTemplate != null && gradeTemplate.CellIndex.HasValue)
            {
                var gradeName = cellInfos[gradeTemplate.CellIndex.Value];
                if (gradeName != gradeInfo.Name)
                {
                    return null;
                }
            }

            return student;
        }
    }
}